#include "mainwidget.h"
#include "./ui_mainwidget.h"

#include "debug.h"
#include <QPushButton>
#include "groupsessiondetailwidget.h"
#include "addfriendwidget.h"
#include "model/datacenter.h"
#include "messageeditarea.h"

//static成员要在类外初始化
MainWidget* MainWidget::instance = nullptr;
MainWidget* MainWidget::getInstance()
{
    if(instance == nullptr)
    {
        instance = new MainWidget();
    }
    return instance;
}

MainWidget::MainWidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MainWidget)
{
    ui->setupUi(this);
    this->setWindowTitle("我的聊天室");
    this->setWindowIcon(QIcon(":/resource/LOGO.png"));

    //初始化主窗口布局
    initMainWindow();
    //初始化左窗口布局
    initLeftWindow();
    //初始化中间窗口布局
    initMidWindow();
    //初始化右窗口布局
    initRightWindow();

    //初始化webSocket
    initWebSocket();
    //连接信号槽，处理按钮被点击的效果
    initSlots();
}

MainWidget::~MainWidget()
{
    delete ui;
}

void MainWidget::initMainWindow()
{
    QHBoxLayout* hlayout = new QHBoxLayout();
    hlayout->setSpacing(0);                 //元素紧挨着
    hlayout->setContentsMargins(0,0,0,0);   //layout离四个边界的距离
    this->setLayout(hlayout);
    leftWidget = new QWidget();
    midWidget = new QWidget();
    rightWidget = new QWidget();

    //设置三个部分的大小
    leftWidget->setFixedWidth(70);
    midWidget->setFixedWidth(330);
    rightWidget->setMinimumWidth(600);
    //设置三部分的颜色
    leftWidget->setStyleSheet("QWidget {background-color:rgb(46,46,46);}");
    midWidget->setStyleSheet("QWidget {background-color:rgb(246,246,246);}");
    rightWidget->setStyleSheet("QWidget {background-color:rgb(240,240,240);}");

    hlayout->addWidget(leftWidget);
    hlayout->addWidget(midWidget);
    hlayout->addWidget(rightWidget);
}

void MainWidget::initWebSocket()
{
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    dataCenter->initWebSocket();
}

void MainWidget::initSlots()
{
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    /**********************************************************************************************
     * 连接信号槽, 处理标签页按钮切换的问题
     **********************************************************************************************/
    // connect(useravatar,&QPushButton::clicked,this,switchToSession);
    connect(sessionTabBtn,&QPushButton::clicked,this,&MainWidget::switchToSession);
    connect(friendTabBtn,&QPushButton::clicked,this,&MainWidget::switchToFriend);
    connect(applyFriendTabBtn,&QPushButton::clicked,this,&MainWidget::switchToApply);

    /**********************************************************************************************
     * 点击自己的头像, 弹出对话框显示个人主页
     **********************************************************************************************/
    connect(useravatar,&QPushButton::clicked,this,[=](){
        SelfInfoWidget* selfInfoWidget = new SelfInfoWidget(this);
        selfInfoWidget->exec();  //弹出模态对话框
    });

    //点击会话页面的更多按钮，弹出会话详细信息
    connect(extraBtn,&QPushButton::clicked,this,[=](){
        model::ChatSessionInfo* chatSessionInfo = dataCenter->findChatSessionById(dataCenter->getCurrentSessionId());
        if(chatSessionInfo == nullptr)
        {
            LOG() << "当前会话不存在";
            return;
        }
        bool isSingleChat = !(chatSessionInfo->userId.isEmpty());
        if(isSingleChat)
        {
            //加载当前的用户
            UserInfo* userInfo = dataCenter->findFriendById(chatSessionInfo->userId);
            if(userInfo == nullptr)
            {
                LOG() << "单聊会话对应的用户不存在，无法弹出";
                return;
            }
            SessionDetailWidget* sessionDetail = new SessionDetailWidget(this,*userInfo);
            sessionDetail->exec();
        }
        else
        {
            GroupSessionDetailWidget* groupSessionDeatil = new GroupSessionDetailWidget(this);
            groupSessionDeatil->exec();
        }

    });


    /**********************************************************************************************
     * 点击添加好友按钮, 弹出添加好友窗口
     **********************************************************************************************/
    connect(addFriendBtn, &QPushButton::clicked, this, [=]() {
        AddFriendWidget* addFriendDialog = new AddFriendWidget(this);
        addFriendDialog->exec();
    });

    /**********************************************************************************************
     * 修改搜索框内容, 弹出添加好友对话框
     **********************************************************************************************/
    connect(searchEdit, &QLineEdit::textEdited, this, [=]() {
        // 取出当前输入框的内容, 设置到新弹框的输入框里面
        const QString& searchKey = searchEdit->text();
        AddFriendWidget* addFriendDialog = new AddFriendWidget(this);
        addFriendDialog->setSearchKey(searchKey);
        // 清空主窗口的文本内容
        searchEdit->setText("");
        addFriendDialog->exec();
    });


    /**********************************************************************************************
     * 通过网络通信，加载用户个人信息头像
     **********************************************************************************************/


    connect(dataCenter,&model::DataCenter::getMyselfDone,this,[=](){
        UserInfo* mysel = dataCenter->getMyself();
        useravatar->setIcon(mysel->avatar);
    });
    dataCenter->getMyselfAsync();

    /**********************************************************************************************
     * 通过网络通信，加载好友列表
     **********************************************************************************************/
    this->loadFriendList();

    /**********************************************************************************************
     * 通过网络通信，加载会话列表
     **********************************************************************************************/
    this->loadSessionList();


    /**********************************************************************************************
     * 通过网络通信，加载好友申请列表
     **********************************************************************************************/
    this->loadApplyList();

    //修改头像
    connect(dataCenter,&model::DataCenter::changeAvatarDone,this,[=](){
        auto* myself = dataCenter->getMyself();
        this->useravatar->setIcon(myself->avatar);
    });

    //清空当前的聊天界面
    connect(dataCenter,&model::DataCenter::clearCurrentSession,this,[=](){
        titleLabel->setText("");
        messageArea->clear();
        dataCenter->setCurrentChatSessionId("");
        LOG() << "清空当前会话完毕";
    });

    connect(dataCenter,&model::DataCenter::deleteFriendDone,this,[=](){
        this->updateFriendList();
        this->updateChatSessionList();
        LOG() << "删除好友完毕";
    });

    //添加好友
    connect(dataCenter,&model::DataCenter::applyFriendDone,this,[=](){
        Toast::showMessage("已发送好友申请!");
    });

    //更新好友申请列表
    connect(dataCenter,&model::DataCenter::receiveFriendApplyDone,this,[=](){
        this->updateApplyList();
    });

    //同意好友申请后,更新界面
    connect(dataCenter,&model::DataCenter::agreeFriendApplyDone,this,[=](){
        this->updateApplyList();
        this->updateFriendList();
        Toast::showMessage("好友申请接收成功!");
    });

    connect(dataCenter,&model::DataCenter::rejectFriendApplyDone,this,[=](){
        this->updateApplyList();
        Toast::showMessage("好友申请已经拒绝!");
    });

    //处理好友申请结果的推送数据
    connect(dataCenter,&model::DataCenter::recevieFriendApplyProcessDone,this,[=](const QString& userName,bool agree){
        if(agree)
        {
            Toast::showMessage(userName + "同意了你的好友申请");
            this->updateFriendList();
        }else
        {
            Toast::showMessage(userName + "拒绝了你的好友申请");
        }
    });

    //处理创建群聊完毕的信号
    connect(dataCenter,&model::DataCenter::createGroupChatSessionDone,this,[=](){
        Toast::showMessage("创建群聊会话请求已经发送!");
    });

    connect(dataCenter,&model::DataCenter::receiveSessionCreateDone,this,[=](){
        this->updateChatSessionList();
        Toast::showMessage("您已被拉入新的群聊!");
    });
}

MessageShowArea *MainWidget::getMessageShowArea()
{
    return messageArea;
}

void MainWidget::switchToSession()
{
    //1.记录当前切换到了哪个标签页，以便midWidget切换
    activeTab = SESSION_LIST;
    //2/调整图标显示
    sessionTabBtn->setIcon(QIcon(":/resource/chat_active"));
    friendTabBtn->setIcon(QIcon(":/resource/friend_inactive"));
    applyFriendTabBtn->setIcon(QIcon(":/resource/app_inactive"));
    //加载会话列表
    this->loadSessionList();
}

void MainWidget::switchToFriend()
{
    activeTab = FRIEND_LIST;
    sessionTabBtn->setIcon(QIcon(":/resource/chat_inactive"));
    friendTabBtn->setIcon(QIcon(":/resource/friend_active"));
    applyFriendTabBtn->setIcon(QIcon(":/resource/app_inactive"));
    //加载会话列表
    this->loadFriendList();
}

void MainWidget::switchToApply()
{
    activeTab = APPLY_LIST;
    sessionTabBtn->setIcon(QIcon(":/resource/chat_inactive"));
    friendTabBtn->setIcon(QIcon(":/resource/friend_inactive"));
    applyFriendTabBtn->setIcon(QIcon(":/resource/app_active"));
    //加载会话列表
    this->loadApplyList();
}

void MainWidget::switchSession(const QString &userId)
{
    //点击好友列表中的好友，切换到会话列表，并且将选中的好友置顶，加载好友的最新消息
    //1.找到点击的好友列表
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    model::ChatSessionInfo* chatSessionInfo = dataCenter->findChatSessionByUserId(userId);
    if(chatSessionInfo == nullptr)
    {
        LOG() << "对应的会话不存在，userId = " << userId;
        return;
    }
    //2.将会话置顶
    dataCenter->topChatSessionInfo(*chatSessionInfo);
    //3.切换到会话标签页,这里会重新加载chatSessionList,刚才添加的也就加载进入了
    this->switchToSession();
    //4.被选中的好友对应的会话，在会话列表的最前面，也就是0下标，将其背景色设置为点击后的效果
    // sessionArea->clickItem(0);
}

void MainWidget::initLeftWindow()
{
    QVBoxLayout* vlayout = new QVBoxLayout();
    vlayout->setSpacing(20);
    vlayout->setContentsMargins(0,30,0,0);
    leftWidget->setLayout(vlayout);     //每个窗口只能有一个布局，此处是左窗口的

    //头像
    useravatar = new QPushButton;
    useravatar->setFixedSize(45,45);
    useravatar->setIconSize(QSize(45,45));
    // useravatar->setIcon(QIcon(":/resource/lion.png"));
    useravatar->setFlat(true);//不想让它有任何 hover 视觉反馈
    //设置居中，靠上对齐
    vlayout->addWidget(useravatar,1,Qt::AlignTop | Qt::AlignHCenter);

    //会话
    sessionTabBtn = new QPushButton();
    sessionTabBtn->setFixedSize(45,45);
    sessionTabBtn->setIconSize(QSize(45,45));
    sessionTabBtn->setIcon(QIcon(":/resource/chat_active.png"));
    sessionTabBtn->setFlat(true);   //不想让它有任何 hover 视觉反馈
    vlayout->addWidget(sessionTabBtn,1,Qt::AlignTop | Qt::AlignHCenter);

    //好友
    friendTabBtn = new QPushButton();
    friendTabBtn->setFixedSize(45,45);
    friendTabBtn->setIconSize(QSize(45,45));
    friendTabBtn->setIcon(QIcon(":/resource/friend_inactive.png"));
    friendTabBtn->setFlat(true);
    vlayout->addWidget(friendTabBtn,1,Qt::AlignTop | Qt::AlignHCenter);

    //好友申请
    applyFriendTabBtn = new QPushButton();
    applyFriendTabBtn->setFixedSize(45,45);
    applyFriendTabBtn->setIconSize(QSize(45,45));
    applyFriendTabBtn->setIcon(QIcon(":/resource/app_inactive.png"));
    applyFriendTabBtn->setFlat(true);
    vlayout->addWidget(applyFriendTabBtn,1,Qt::AlignTop | Qt::AlignHCenter);
    //将上面的元素挤上去
    vlayout->addStretch(20);
}

void MainWidget::initMidWindow()
{
    QGridLayout* glayout = new QGridLayout();
    // glayout->setSpacing(0);
    glayout->setHorizontalSpacing(0);
    glayout->setVerticalSpacing(8);
    glayout->setContentsMargins(0,30,0,0);
    midWidget->setLayout(glayout);

    //搜索框
    searchEdit = new QLineEdit();
    searchEdit->setFixedHeight(30);
    searchEdit->setPlaceholderText("搜索");
    searchEdit->setStyleSheet("QLineEdit { border-radius: 5px; background-color: rgb(226,226,226);padding-left:5px;}");

    //添加按钮
    addFriendBtn = new QPushButton();
    addFriendBtn->setFixedSize(30,30);
    addFriendBtn->setIcon(QIcon(":/resource/add.png"));
    QString style = "QPushButton { border-radius: 5px; background-color: rgb(226,226,226);}";
    style += "QPushButton:press { background-color: rgb(240,240,240);}";
    addFriendBtn->setStyleSheet(style);

    //会话列表区域
    sessionArea = new SessionFriendArea();

    //创建空白widget，添加到布局管理器中，以便作为空白占位
    QWidget* space1 = new QWidget();
    space1->setFixedWidth(10);
    QWidget* space2 = new QWidget();
    space2->setFixedWidth(10);
    QWidget* space3 = new QWidget();
    space3->setFixedWidth(10);
    glayout->addWidget(space1,0,0);
    glayout->addWidget(searchEdit,0,1);
    glayout->addWidget(space2,0,2);
    glayout->addWidget(addFriendBtn,0,3);
    glayout->addWidget(space3,0,4);
    glayout->addWidget(sessionArea,1,0,1,5);    //横跨1行，5列
}

void MainWidget::initRightWindow()
{
    //1.创建右窗口的垂直布局
    QVBoxLayout* vlayout = new QVBoxLayout();
    vlayout->setSpacing(0);
    vlayout->setContentsMargins(0,0,0,0);
    vlayout->setAlignment(Qt::AlignTop);
    rightWidget->setLayout(vlayout);

    //2.标题栏
    QWidget* titleWidget = new QWidget();
    titleWidget->setFixedHeight(55);
    titleWidget->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed);
    //添加标题栏与消息列表之间的框线
    titleWidget->setObjectName("titleWidget");
    titleWidget->setStyleSheet("#titleWidget { border-bottom: 1px solid rgb(230, 230, 230); border-left: 1px solid rgb(230, 230, 230); }");
    vlayout->addWidget(titleWidget);

    //3.给标题栏添加标题、按钮
    QHBoxLayout* hlayout = new QHBoxLayout();
    hlayout->setSpacing(0);
    hlayout->setContentsMargins(10,0,10,0);
    titleWidget->setLayout(hlayout);
    titleLabel = new QLabel();
    titleLabel->setStyleSheet("QLabel{font-size:18px;}");
#ifdef TEST_UI
    titleLabel->setText("这是一个标题栏");
#endif
    extraBtn = new QPushButton();
    extraBtn->setFixedSize(40,30);
    extraBtn->setIconSize(QSize(40,30));
    extraBtn->setIcon(QIcon(":/resource/extra.png"));
    extraBtn->setStyleSheet("QPushButton{ border:none; background-color:rgb(240, 240, 240); } QPushButton:pressed{background:rgb(230,230,230)}");
    hlayout->addWidget(titleLabel);
    hlayout->addWidget(extraBtn);

    //4.添加消息展示区
    messageArea = new MessageShowArea();
    vlayout->addWidget(messageArea);
    //5.添加消息编辑区
    messageEditArea = new MessageEditArea();
    vlayout->addWidget(messageEditArea);
}

void MainWidget::loadSessionList()
{
    //会话列表数据实在DataCenter中存储的
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    if(dataCenter->getChatSessionList() != nullptr)
    {
        updateChatSessionList();
    }
    else
    {
        connect(dataCenter,&model::DataCenter::getChatSessionListDone,this,&MainWidget::updateChatSessionList,Qt::UniqueConnection);
        dataCenter->getChatSessionListAsync();
    }
}

void MainWidget::loadFriendList()
{
    //好友列表数据是在DataCenter中存储的，
    //首先判断DataCenter中是否已经有数据了；
    //有数据，直接加载；没有数据，网络获取
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    if(dataCenter->getFriendList() != nullptr)
    {
        //从内存加载
        updateFriendList();
    }
    else
    {
        //设置响应接收后的处理方式
        connect(dataCenter,&model::DataCenter::getFriendListDone,this,&MainWidget::updateFriendList,Qt::UniqueConnection);
        //通过网络获取
        dataCenter->getFriendListAsync();
    }
}

void MainWidget::loadApplyList()
{
     model::DataCenter* dataCenter = model::DataCenter::getInstance();
    if(dataCenter->getApplyList() != nullptr)
    {
        //从内存加载
        updateApplyList();
    }
    else
    {
        //设置响应接收后的处理方式
        connect(dataCenter,&model::DataCenter::getAppalListDone,this,&MainWidget::updateApplyList,Qt::UniqueConnection);
        //通过网络获取
        dataCenter->getApplyListAsync();
    }
}

void MainWidget::loadRecentMessage(const QString &chatSessionId)
{
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    if(dataCenter->getRecentMessageList(chatSessionId) != nullptr)
    {
        //内存中加载
        updateRecentMessage(chatSessionId);
        LOG() << "从内存中加载近期消息列表";
    }
    else
    {
        connect(dataCenter,&model::DataCenter::getRecentMessageDone,this,&MainWidget::updateRecentMessage,Qt::UniqueConnection);
        dataCenter->getRecentMessageAsync(chatSessionId,true);
        LOG() << "从网络中加载近期消息列表,会话ID：" << chatSessionId;
    }
}

//从内存中加载
void MainWidget::updateFriendList()
{
    //如果当前未选中好友列表标签页
    if(activeTab != ActiveTab::FRIEND_LIST)
    {
        return;
    }

    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    QList<UserInfo>* friendList = dataCenter->getFriendList();

    //清空一下之前界面上的数据
    sessionArea->clear();

    //遍历好友列表，添加上
    for(auto& e : *friendList)
    {
        sessionArea->addItem(ItemType::FRIENDITEM_TYPE,e.userId,e.avatar,e.nickName,e.description);
    }

}

void MainWidget::updateChatSessionList()
{
    if(activeTab != ActiveTab::SESSION_LIST)
    {
        return;
    }

    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    QList<model::ChatSessionInfo>* chatSessionList = dataCenter->getChatSessionList();
     // LOG() << "进入到updateChatSessionList111111";
    // if(chatSessionList == nullptr)
    // {
    //     LOG() << "chatSessionList == nullptr";
    //     return;
    // }
    sessionArea->clear();
    // LOG() << "进入到updateChatSessionList222222";
    for(const auto& e : *chatSessionList)
    {

        if(e.prevMessage.messageType == model::MessageType::TEXT_TYPE)
        {
            sessionArea->addItem(ItemType::SESSIONITEM_TYPE,e.sessionId,e.avatar,e.sessionName,e.prevMessage.content);
        }
        else if(e.prevMessage.messageType == model::MessageType::FILE_TYPE)
        {
            sessionArea->addItem(ItemType::SESSIONITEM_TYPE,e.sessionId,e.avatar,e.sessionName,"[文件]");
        }
        else if(e.prevMessage.messageType == model::MessageType::IMAGE_TYPE)
        {
            sessionArea->addItem(ItemType::SESSIONITEM_TYPE,e.sessionId,e.avatar,e.sessionName,"[图片]");
        }
        else if(e.prevMessage.messageType == model::MessageType::SPEECH_TYPE)
        {
            sessionArea->addItem(ItemType::SESSIONITEM_TYPE,e.sessionId,e.avatar,e.sessionName,"[语音]");
        }
        else
        {
            // LOG() << "prevMessage类型错误:" << e.prevMessage.messageType;
            // return;
            sessionArea->addItem(ItemType::SESSIONITEM_TYPE,e.sessionId,e.avatar,e.sessionName,"");
        }
    }
}

void MainWidget::updateApplyList()
{
    if(activeTab != ActiveTab::APPLY_LIST)
    {
        return;
    }

    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    QList<UserInfo>* applyList = dataCenter->getApplyList();

    //清空一下之前界面上的数据
    sessionArea->clear();

    //遍历好友列表，添加上
    for(auto& e : *applyList)
    {
        sessionArea->addItem(ItemType::APPLYITEM_TYPE,e.userId,e.avatar,e.nickName,e.description);
    }
}

void MainWidget:: updateRecentMessage(const QString &chatSessionId)
{
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    QList<MessageInfo>* recentMessageList = dataCenter->getRecentMessageList(chatSessionId);
    //1.清空原有界面上的消息列表
    messageArea->clear();
    //2.根据消息列表，加载消息显示
    //此处把消息显示在界面上，采用头插法，使最近的消息显示在最下面
    for(int i = recentMessageList->size() - 1; i >= 0; --i)
    {
        const MessageInfo& message = recentMessageList->at(i);
        //消息ID不等于 当前用户ID，放在左侧
        bool isLeft = message.userInfo.userId != dataCenter->getMyself()->userId;
        messageArea->addFrontMessage(isLeft,message);
    }

    //3.设置会话标题
    model::ChatSessionInfo* chatSesionInfo = dataCenter->findChatSessionById(chatSessionId);
    if(chatSesionInfo != nullptr)
    {
        titleLabel->setText(chatSesionInfo->sessionName);
    }

    //4.保存当前的会话是哪个
    dataCenter->setCurrentChatSessionId(chatSessionId);

    //5.滚动条自动到末尾
    messageArea->scrollToEnd();

}
